#include "PureString.h"
#include <string.h>
#include <assert.h>
#include <stdio.h>

namespace Pure
{
    
#define PAlign4(x)  ((x + 3) >> 2 << 2)

char* strndup(const char* src, size_t len)
{
    assert(len >= 0);
    assert(src);
    if (!len)
        return NULL;
    char* dest = (char*)malloc(len);
    memcpy(dest, src, len);
    return dest;
}

String::~String()
{
    free(mData);
}

void String::append(const char utf8[], size_t len)
{
    if (len)
    {
        size_t newLen = mLength + len;
        if (mLength < newLen)
        {
            mData = (char*)realloc(mData, newLen + 1);
            assert(mData);
        }
        memcpy(mData + mLength, utf8, len);
        mLength = newLen;
        mData[mLength] = NULL;
    }
}

void String::append(const char utf8[])
{
    if (utf8)
        this->append(utf8, strlen(utf8));
}

void String::clear(bool freeData)
{
    mLength = 0;
    mData[0] = NULL;
    if (freeData)
    {
        free(mData);
        mData = 0;
    }
}

bool String::equals(const char utf8[], size_t len) const
{
    return this->mLength == len && !memcmp(utf8, this->mData, len);
}

bool String::equals(const char utf8[]) const
{
    if (utf8)
        return this->equals(utf8, strlen(utf8));
    return this->mData == NULL && this->mLength == 0;
}

void String::allocData(const char utf8[], size_t len)
{
    char* buff = NULL;
    if (len == 0)
        this->clear(true);
    if (len)
    {
        if (mData)
            buff = (char*)realloc(mData, len + 1);
        else
            // Allocate the length and null-terminator
            buff = (char*)malloc(len + 1);
        assert(buff);
#ifdef PURE_DEBUG
        // TODO: Move all mallocs into a function that will zero-out the
        // memory if in debug mode. This function could also be used to
        // prepend data to identify memory blocks.
        memset(buff, 0, len);
#endif
        if (utf8)
            memcpy(buff, utf8, len);
        buff[len] = NULL;
    }
    mLength = len;
    mData = buff;
}

void String::allocData(const char utf8[])
{
    if (utf8)
        this->allocData(utf8, strlen(utf8));
}

}
